Skip to content

feat(search): honest has-preview prop and thumbnails relationship - #3210

Draft
dschmidt wants to merge 18 commits into
feat/thumbnails-raw-embedded-previewfrom
feat/search-preview-presence
Draft

dschmidt wants to merge 18 commits into
feat/thumbnails-raw-embedded-previewfrom
feat/search-preview-presence

Conversation

@dschmidt

@dschmidt dschmidt commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Makes preview availability honest instead of a blanket mimetype match, and bases the driveItem thumbnails on it.

  • Split the preview types into unconditional ones and those that carry their preview inside the file + HasPreview as the single source of truth (unconditional types follow from the mimetype, an audio cover depends on what the index saw). Both live in services/webdav/pkg/thumbnail now, where webdav owns the type list since Push based thumbnailer architecture #3397.
  • Index the embedded cover: its dimensions and the type it is in, as oc.preview (preferring the front cover).
  • The thumbnail of a cover is written in the cover's own type: webdav reads oc.preview.contentType when it stats the file, so the output type is settled before the cache key is built and a png cover stays a png. Nothing is derived from the image bytes, and the cache keeps its interface.
  • No indexed cover, no preview. Without dimensions and type nothing can say what the thumbnail would be, so webdav answers 404 instead of extracting and guessing a format. The type mapping no longer pins audio to jpeg.
  • Honest oc:has-preview for audio in search results (new preview field on the search message entity).
  • Graph driveItem thumbnails ($expand=thumbnails) are gated on HasPreview and gain a source thumbnail requested at the original size. No thumbnail carries dimensions: the served size snaps to the configured resolution set, not knowable at listing time.

Stacked on #3332, which is what closes the gap this PR used to carry: the preview metadata and the rendered preview now come from the same extraction, so they cannot describe different pictures. What is indexed is what gets rendered.

Removing a cover does not clear an already indexed oc.preview yet. The stale facet cleanup in #3682 only covers the libre.graph. prefix, so whichever of the two merges last has to add oc.preview. to its stale check.

Follow-ups (kept out to stay focused): consolidate the shared-view thumbnail blocks via a generic odata expand-set, and switch reva propfind has-preview to thumbnail.HasPreview.

  • Show the audio artwork in the preview app. With oc.preview saying that a track carries a cover, and in which type, the web preview app can show it when an audio file is opened, the way a player shows album art, instead of a generic icon. Needs the source thumbnail from the thumbnails relationship on the web side, nothing further on the server.

Note for later: with previews gated on the index, webdav knows a source's dimensions before it fetches anything. The source ceiling (THUMBNAILS_MAX_INPUT_WIDTH/HEIGHT) is enforced in the generator today because it is the only one that sees pixels, and it could then be answered upstream instead: has-preview says false and the request ends in a 404, without a download and without a decode.

Note

Even once this PR and #3211 (graph search query endpoint) are both merged, hits from POST /graph/v1beta1/search/query still won't carry thumbnails: the $expand=thumbnails wiring for search hits builds on both PRs and currently only exists on the consolidation branch (dschmidt/opencloud@feat/graph-search-full-2, commit 0d94199a: searchEntityThumbnailSet in searchquery.go, preview presence via thumbnail.HasPreviewForMimeType + indexed oc.preview/image-facet dimensions). It needs a follow-up PR once both are in.

@codacy-production

codacy-production Bot commented Jul 30, 2026 •

Copy link
Copy Markdown

Not up to standards ⛔

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@dschmidt
dschmidt force-pushed the feat/search-preview-presence branch from 5748d3c to 8d0b8ed Compare July 30, 2026 18:31
@dschmidt dschmidt changed the title feat(search): honest previews and driveItem thumbnails relationship feat(search): honest has-preview and driveItem thumbnails relationship Jul 30, 2026
@dschmidt dschmidt changed the title feat(search): honest has-preview and driveItem thumbnails relationship feat(search): honest has-preview and thumbnails relationship Jul 30, 2026
@dschmidt dschmidt changed the title feat(search): honest has-preview and thumbnails relationship feat(search): honest has-preview prop and thumbnails relationship Jul 31, 2026
@dschmidt
dschmidt force-pushed the feat/search-preview-presence branch from 72d4dcb to 3027a39 Compare August 18, 2026 16:36
Comment on lines +11 to +14
const (
PreviewWidthKey = "oc.preview.width"
PreviewHeightKey = "oc.preview.height"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer a single oc.preview property with 200x300 as the dimension. While we do cache the properties in nats, I think splitting by x is more efficient.

@dschmidt dschmidt Aug 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not the biggest fan tbh.

Would need concatenation on the indexing site and parsing on the consuming side, while making querying for it more awkward and require special handling.
I could imagine for my music server it could be nice for some views to query only files with specific (minimal) preview sizes e.g.

If you insist, we can do it.. but I'd prefer not to

@butonic

butonic commented Aug 27, 2026

Copy link
Copy Markdown
Member

Hm ...

I need the availability and dimensions of embedded previews at index time (#3210).

🤔

You mean you need them to be created when indexing (after postprocessing), so they are available during dirlistings?

@dschmidt

Copy link
Copy Markdown
Contributor Author

I need the availability and dimensions of embedded previews at index time (#3210).

You mean you need them to be created when indexing (after postprocessing), so they are available during dirlistings?

Basically, yes - I need the dimensions in ArbitraryMetadata during listings and in the index during search, so I can fill the thumbnails relationship.
It's basically the same as all the other extracted metadata like audio artists, geo data in images, etc.
This was the original motivation to implement the extraction in Tika, so it's completely anologous to the other metadata extraction, because that seemed like a completely natural fit.
The only downside of doing it like this is, that previews for files out of the EmbeddedPreviewMimeTypes group become available only when they have been indexed.

@dschmidt
dschmidt changed the base branch from feat/search-tika-facets to main September 1, 2026 08:44
@dschmidt
dschmidt force-pushed the feat/search-preview-presence branch 7 times, most recently from 9de577a to 3bf02cf Compare September 3, 2026 08:25
@dschmidt
dschmidt changed the base branch from main to feat/graph-expand-thumbnails September 6, 2026 21:48
Tika merged the thumbnail catalog preset and ThumbnailUnpackSelector
(TIKA-4856): PUT /unpack/preset/thumbnail returns exactly the one raster
image a client would show for the document - a stored thumbnail, the
rendering of a metafile thumbnail, or the rendered first page. The
client-side selection over /unpack/all (embedded-resource-type marks,
metafile renderings, id-path matching) moves to the server; the preset
zip carries one image without metadata sidecars, so the entry's
extension names the type and the bytes break the tie. A 404 now points
at the preset activation the server config needs.
The preset ships inert in tika-pipes-core, so PUT /unpack/preset/thumbnail
answers 404 until a config names it, and the thumbnailer then finds no
thumbnail for any document. The acceptance stack and the example
deployment now pass a config that activates it, and the deployment reads
the shared OC_TIKA_URL so the thumbnailer uses the Tika that is already
there. The acceptance image goes to 4.1, the release the preset is in.
The cache key is derived from configuration again: a thumbnail is written in
the type the file's own type maps to, so the answer no longer depends on what
Tika hands back and needs no placeholder in the key.

Which types Tika gets is decided in one place now. An image type goes to Tika
only when a deployment names it, because the generator behind the URL may read
it itself, which also lets a raw photo reach Tika at all.
Unconditional types follow from the mimetype, embedded ones (audio cover art) need indexed oc.preview dimensions.
Prefers the front cover. Adds the preview field to the search entity.
oc.preview now carries the cover's own content type next to its dimensions, so
webdav knows before it builds the cache key what a thumbnail of it is written
in: a png cover stays a png instead of being re-encoded to the jpeg the
container's type maps to.
A file that carries its preview inside is only previewable once the extraction
has seen it: dimensions and the type it is in. Without that nothing here could
say what a thumbnail would be, so the mapping no longer pins audio to jpeg and
the workflow refuses instead of guessing.
@dschmidt
dschmidt force-pushed the feat/search-preview-presence branch from 44b3378 to 66cfa4b Compare October 19, 2026 14:13
@dschmidt
dschmidt force-pushed the feat/search-preview-presence branch from 4bb189c to a860742 Compare October 19, 2026 15:09
// unpacker's thumbnail preset extracts that same image, so the index reports
// what the thumbnailer serves. A file that needs no such image, an image
// itself for one, has no marked part.
var thumbnailResourceTypes = []string{"THUMBNAIL", "RENDERING"}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double check the logic how tika sets what and what should be prioritized

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants